/*
 * 导出文件
 * @data 后台返回的数据流
 * @fileName 导出的文件名
*/
export function exportFile(data, fileName) {
  const link = document.createElement('a')
  let blob = new Blob([data], {type: 'application/vnd.ms-excel'})
  link.style.display = 'none'
  link.href = URL.createObjectURL(blob)
  link.download = fileName
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

/*
 * 上传图片格式校验
 * @file *文件流
 * @megabyte 限制大小 单位兆
*/
export function beforeUpload(file, megabyte = 5) {
  const isFormat = file.raw.type === 'image/jpeg' || file.raw.type === 'image/png' || file.raw.type === 'image/gif'
  const isMegabyte = file.size / 1024 / 1024 < megabyte;
  let error
  if (!isFormat) error = '上传图片只能是JPG/PNG/GIF格式!'
  if (!isMegabyte) error = `上传图片大小不能超过 ${megabyte}MB!`
  return error
}

/*
 * 生成随机数
 * length *指定长度
*/
export function randomNum(length) {
  let ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  ALPHABET += 'abcdefghijklmnopqrstuvwxyz';
  ALPHABET += '0123456789-_';
  let str = '';
  for (let i = 0; i < length; ++i) {
    let rand = Math.floor(Math.random() * ALPHABET.length);
    str += ALPHABET.substring(rand, rand + 1);
  }
  return str;
}

/*
* 查询字符串中子串出现的下标
* str 字符串
* substr 子串
* */
export function search_substr_pos(str, substr) {
  let _search_pos = str.indexOf(substr), _arr_positions = [];
  while (_search_pos > -1) {
    _arr_positions.push(_search_pos);
    _search_pos = str.indexOf(substr, _search_pos + 1);
  }
  return _arr_positions;
}

/*
* 查找数组中重复值
* arr 查询的数组对象
* state: 1.index 返回 重复相应下标组 2. value 返回相同值
* */
export function getDuplicate(arr,state = 'index'){
  let str = "";
  let list = [];
  let returnIndex = []
  let returnValue = []
  for (var i = 0; i < arr.length; i++) {
    let hasRead = false;
    for ( var k = 0; k < list.length; k++) {
      if (list[k] == arr[i]){ hasRead = true; }
    }
    if(!hasRead){
      let _index = i, haveSame = false;
      for (var j = i + 1; j < arr.length; j++) {
        if (arr[i] == arr[j]) {
          _index += "," + j;
          haveSame = true;
        }
      }
      if (haveSame) {
        list.push(arr[i]);
        returnIndex.push(_index)
        returnValue = arr[i]
        str += "数组下标为"+_index+"，相同值为"+arr[i]+ "\n";
      }
    }
  }
  if(state === 'index') return returnIndex  // 获取重复值相应下标
  else return str     // 对应下标 重复的value值
}

/**
 * 判断数组中是否存在重复数据
 * true   存在重复数据
 * false  不存在重复数据（该js数组中只要存在一条重复数据  就会返回true）
 */
export function isRepeat(arr) {
  if(!arr || arr.length < 1){
    return false;
  }
  let hash = {};
  for (let i in arr) {
    if (hash[arr[i]]) {
      return true;
    }
    hash[arr[i]] = true;
  }
  return false;
}

/*
* 查询一组 数组日期是否为连续日
* days 数组日期 ["2022-02-26","2022-02-27","2022-03-01", "2022-03-04","2022-03-05""]
* return 返回 连续日期value  ["2022-02-26,2022-02-27","2022-03-04,2022-03-04"]
* */
export function getDaySequence(daysArr){
  let _days = daysArr.sort().map((d, i) => {
    let dt = new Date(d)
    dt.setDate(dt.getDate() + 4 - i) // 处理为相同日期
    return +dt
  })
  let returnDays = []
  let getDaySequenceData = getDuplicate(_days)
  if(getDaySequenceData.length != 0){
    getDaySequenceData.forEach(item=>{
      let str = []
      item.split(',').forEach(itemIndex=>{
        str.push(daysArr[itemIndex])
      })
      str = str.join(',')
      returnDays.push(str)
    })
  }
  return returnDays
}

/* 自定义数据类 */
export class CustomData {

}

/* 自定义对象类 */
export class CustomObject extends CustomData{
  constructor(obj) {
    super()
    this.obj = obj
  }
  /* 移除一维或二维对象中值为空的属性 */
  filterKey(){
    let newObj = {}
    for (let k1 in this.obj) {
      for (let k2 in this.obj[k1]) {
        if (this.obj[k1][k2] !== '') {
          newObj[k1] === undefined && (newObj[k1] = {})
          newObj[k1][k2] = this.obj[k1][k2]
        }
      }
    }
    return newObj
  }
}

/* 自定义数组类 */
export class CustomArray extends CustomData{
  constructor(arr) {
    super()
    this.arr = arr
  }
  /*
   * 修改数组中对象的字段名称
   * @newKey *新字段名称
   * @oldKey *旧字段名称
  */
  changeKey(newKey, oldKey) {
    for (const item of this.arr) for (const key in item) key === oldKey && (item[newKey] = !item[key], delete item[key])
    return this.arr
  }
  /*
   * 数组/数组对象去重
  */
  unique() {
    const map = new Map()
    return this.arr.filter(item => !map.has(JSON.stringify(item)) && map.set(JSON.stringify(item), 1))
  }
}

/* 表单正则验证类 */
class VerificationRule {
  constructor() {
    this.reg = ''
    this.reg_1 = ''
  }
  /* 手机号验证 */
  mobile(value) {
    this.reg = /^1[3-9][0-9]{9}$/
    this.reg_1 = /0\d{2,3}-\d{7,8}/
    return !this.reg.test(value) && !this.reg_1.test(value)
  }
  /* 身份证验证 */
  certificateNo(value) {
    this.reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
    return !this.reg.test(value)
  }
  /* 邮箱验证 */
  email(value) {
    this.reg = /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
    return !this.reg.test(value)
  }
  /* 整数 */
  integer(value) {
    this.reg = /^[0-9]+$/;
    return !this.reg.test(value)
  }
  decimal(value) {
    this.reg = /^(([1-9][0-9]{0,14})|(([0]\.[0-9][1-9]|[0]\.[1-9][0-9]|[0]\.[1-9]|[0]\.[1-9][1-9]|[1-9][0-9]{0,14}\.\d{1,2})))/;
    return !this.reg.test(value)
  }
  /*
   * 字符串最小及最大长度验证
   * @fromTo *最小-最大长度 例：[1,5]
  */
  scopeLength(value, fromTo) {
    this.reg = eval( '/^[\\u4e00-\\u9fa5]{'+ fromTo[0] +','+ fromTo[1] +'}$/');
    return !this.reg.test(value)
  }
  /*
   * 字符串最小长度验证
   * @fromTo *最小长度
  */
  minLength(value, fromTo) {
    this.reg = eval('/^[\\u4e00-\\u9fa5A-Za-z0-9]{'+ fromTo[0] +',}$/')
    return !this.reg.test(value)
  }
}
export const verificationRule = new VerificationRule()

/* 日期处理类 */
export function DateFactory(date = new Date()){
  this.date = new Date(date)
  this.year = this.date.getFullYear()
  this.nowDayOfWeek = this.date.getDay() - 1;
  this.month = this.date.getMonth()
  this.day = this.date.getDate()
  this.weekDay = this.date.getDay()
  this.hours = this.date.getHours()
  this.minutes = this.date.getMinutes()
  this.seconds = this.date.getSeconds()
  this.time = this.date.getTime()
}
Object.assign(DateFactory.prototype, {
  /*
   * Date()对象格式化转换
   * @falg 是否显示时分秒 值true=显示 false=不显示
   * return yyyy-MM-dd HH:mm:ss
  */
  dateFormat(falg = true) {
    let MM = this.month + 1 < 10 ? "0"+(this.month + 1) : this.month + 1
    let dd = this.day < 10 ? "0" + this.day : this.day
    let HH = this.hours < 10 ? "0" + this.hours : this.hours
    let mm = this.minutes < 10 ? "0" + this.minutes : this.minutes
    let ss = this.seconds < 10 ? "0" + this.seconds : this.seconds
    let formatDate = this.year + "-" + MM + "-" + dd
    this.constructor()
    return falg ? formatDate + " "+ HH + ":" + mm + ":" + ss : formatDate
  },
  /*
   * 时间戳格式化转换
   * @timestamp *时间戳
   * return yyyy-MM-dd HH:mm:ss
  */
  timestampFormat(timestamp, flag) {
    let date = new Date(parseInt(timestamp) * 1000);
    this.constructor(date)
    return this.dateFormat(flag)
  },
  /*
   * yy-MM-dd HH:mm:ss格式化转换
   * @time *日期 格式=yy-MM-dd HH:mm:ss
   * return 时间戳
  */
  changeTimestamp(date) {
    this.constructor(date.replace(/-/g,'/'))
    let timeStamp = this.time.toString().substr(0, 10)
    this.constructor()
    return timeStamp
  },
  /*
   * 获取距离当前时间某天数的日期
   * @days 天数 值：0=今天;1=明天;-1=昨天...
   * @falg 是否显示时分秒
   * return 格式：yyyy-MM-dd HH:mm:ss
  */
  getDistanceToday(days = 0, falg = true) {
    this.date.setDate(this.date.getDate() + days)
    this.constructor(this.date)
    return this.dateFormat(falg)
  },
  /*
   * 获取距离指定时间某天数的日期
   * @date 指定日期 格式:yyyy-MM-dd HH:mm:ss
   * @method +或-
   * @days 天数 类型:int
   * @flag 是否只留年月日
   * return 格式：yyyy-MM-dd HH:mm:ss
  */
  getDistanceAppoint(date, method = '+', days, flag) {
    let timestamp = Date.parse(date.replace(/-/g, '/'));
    if(method === '+') timestamp = timestamp / 1000 + 24 * 60 * 60 * days;
    if(method === '-') timestamp = timestamp / 1000 - 24 * 60 * 60 * days;
    return this.timestampFormat(timestamp, flag);
  },
  /*
   * 获取上周/本周的开始(周一)/结束(周日)日期
   * @type 周类型 值：the=本周;last=上周;next=下周
   * @fromDate 开始日期或结束日期 值：start=周一;end=周日
   * @falg 是否显示时分秒
  */
  getWeekDate(type = 'the', fromDate = 'start', falg = true) {
    let num = 0
    if (type === 'last') num = fromDate === 'start' ? 7 : 1
    if (type === 'the') num = fromDate === 'start' ? 0 : -(6 - this.nowDayOfWeek)
    if (type === 'next') num = fromDate === 'start' ? -7 : -13
    let date
    if (type === 'the' && fromDate === 'end') date = new Date(this.year, this.month, this.day - num);
    else date = new Date(this.year, this.month, this.day - this.nowDayOfWeek - num);
    this.constructor(date)
    return this.dateFormat(falg)
  },
  /*
   * 获取本月的开始/结束日期
   * @fromDate 开始或结束日期
  */
  getMonthDate(fromDate = 'start', falg = true) {
    let date
    if (fromDate === 'start') date = new Date(this.year, this.month, 1)
    if (fromDate === 'end') date = new Date(this.year, this.month, this.getMonthDays(this.month));
    this.constructor(date)
    return this.dateFormat(falg);
  },
  /*
   * 获得某月的天数
   * @month *当前月份
  */
  getMonthDays(month) {
    let monthStartDate = new Date(this.year, month, 1);
    let monthEndDate = new Date(this.year, month + 1, 1);
    let days = (monthEndDate - monthStartDate) / (1000 * 60 * 60 * 24);
    return days;
  },
  /*
   * 获取本周日期列表
   * return 日期数组
  */
  getWeekList() {
    let arr = []
    this.date = new Date()
    for (let i = 1; i < 8; i++) {
      this.date = new Date(this.time + (i - this.weekDay) * 24 * 60 * 60 * 1000)
      this.constructor(this.date)
      arr.push(this.dateFormat(false))
    }
    return arr
  },
  /*
   * 比较两个时间大小
   * @startTime *起始时间 格式:标准时间/yyyy-MM-dd HH:mm:ss
   * @endTime *结束时间
   * return true/false
  */
  compareTime(startTime, endTime) {
    return new Date(startTime).getTime() > new Date(endTime).getTime()
  },
  /*
   * 获取指定区间的全部日期
   * @startDate *起始日期 格式：yyyy-MM-dd
   * @endDate *结束日期
   * return []日期列表
  */
  getDateRange(startDate, endDate) {
    let dateRange = [];
    let i = 0;
    while(startDate <= endDate){
      dateRange[i] = startDate;
      let nextDate = new Date(startDate).getTime() + ( 24 * 60 * 60 * 1000);
      this.constructor(nextDate)
      startDate = this.dateFormat(false)
      i++;
    }
    return dateRange;
  },
  /*
   * 获取两个日期距离天数
   * @startDate *起始日期
   * @endDate *截止日期
   * bool *精确时分秒
   * return 天数
  */
  getDistanceDays(startDate, endDate,bool) {
    let days = new Date(endDate).getTime() - new Date(startDate).getTime()
    if(bool) return days
    return parseInt(days / (1000 * 59 * 60 * 24));
  }
})
export const dateFactory = new DateFactory()

export default {
  exportFile,
  verificationRule,
  beforeUpload,
  dateFactory,
  CustomArray,
  CustomObject,
  randomNum,
  search_substr_pos,
  getDuplicate,
  isRepeat,
  getDaySequence,
}
